home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / C / Comet2.1.3.cpt / Comet / tftp_util.c < prev    next >
Text File  |  1991-02-11  |  18KB  |  807 lines

  1. /*  Copyright 1984 by the Massachusetts Institute of Technology  */
  2.  
  3. /*
  4.     Copyright Cornell University 1986.  All rights are reserved.
  5.  
  6.     As of 4/10/86:
  7.     This source file may have no changes from the M.I.T original
  8.     other than this notice; but it has been tested as part of 
  9.     Cornell's Aztec-C port.  See notice.h
  10.  
  11. */
  12.  
  13.  
  14. /*  See permission and disclaimer notice in file "notice.h"  */
  15. #include    <notice.h>
  16.  
  17. #include    <em.h>
  18. #include    <h19.h>
  19. #include    "tftp.h"
  20.  
  21. #ifndef DUALTCP
  22. /* declarations needed if MacTCP stands alone */
  23.  
  24. int (*tfs_alert)();
  25. int (*tfs_done)();
  26.  
  27. char macfile[256];            /* for Macintosh file name translation */
  28.  
  29. int ntftps = 0;
  30.  
  31.  
  32. int tfstate = OFF;
  33. long refusedt = 0;            /*  time of most recent transfer refusal  */
  34.  
  35. static unsigned socket = 0;
  36.  
  37. unsigned short udp_socket() 
  38. {
  39.     if (socket) 
  40.         return socket++;
  41.  
  42.     socket = cticks;
  43.     if (socket < 1000) 
  44.         socket +=1000;
  45.     return(socket++);
  46. }
  47.  
  48.  
  49. #endif
  50.  
  51. extern unsigned NDEBUG;
  52.  
  53. #define MINTICKS 60        /* 1 second */
  54.  
  55. extern int (*tfs_alert)();
  56. extern int (*tfs_done)();
  57.  
  58. extern char macfile[];            /* for Macintosh file name translation */
  59.  
  60.  
  61. extern int tfstate;
  62. extern long refusedt;            /*  time of most recent transfer refusal  */
  63.  
  64.  
  65. /* Utility routines */
  66.  
  67. /* Modified to eliminate dangerous resends, simplify round-trip
  68.    time estimation, identify old and extra connections and shut
  69.    them down, and use clock-tick timer, 12/83.
  70.    Modified to use standard error code for old TID's and to byte-
  71.    swap the error code.  12/23/83.
  72.    Modified to check foreign port number before considering 
  73.    error packets to be meaningful.  Also arranged to send
  74.    error packets back in the incoming packet buffer, to
  75.    avoid clobbering the current output packet, 1/84.  
  76.    Initialization of new connections improved to set file descriptor
  77.    and udp connection pointers to null, to avoid errors on premature
  78.    cleanup, 1/16/84.  <J.H.Saltzer>
  79.  
  80.    1/24/84 - added octet mode.
  81.                     <John Romkey>
  82.    1/2/85  - fixed length calculation bug in mtcp_tfudperr.
  83.                     <John Romkey>
  84. */
  85.  
  86. extern char *malloc();
  87. unsigned long getmyA5();
  88.  
  89. ip_addr p_host;                /* source host of current packet */
  90. unsigned short p_port;        /* source port of current packet */
  91.  
  92. extern StreamPtr tfsstream;
  93. extern StreamPtr tftpstream;
  94. extern UDPiopb udpread;
  95.     
  96. /* the TCP Async Notification Routine */
  97.  
  98. pascal void udp_event(stream, eventCode, userDataPtr, icmpMsg)
  99. StreamPtr stream;
  100. short eventCode;
  101. Ptr userDataPtr;
  102. ICMPReport *icmpMsg;
  103. {
  104.     unsigned long oldA5;
  105.     
  106.     oldA5 = getmyA5(); 
  107.     
  108.     switch (eventCode) {
  109.         case UDPDataArrival: {
  110. #ifdef DATANOTIFY
  111.             if (stream == tftpstream)
  112.                 tftpdata = TRUE;
  113.             else if (stream == tfsstream)
  114.                 tfsdata = TRUE;
  115. #endif
  116.             break;
  117.         }
  118.         case UDPICMPReceived: {
  119.             /* prerr25("UDP ICMP Receive"); */
  120.             break;
  121.         }
  122.     }
  123.     
  124.     setA5(oldA5);
  125.  
  126. }
  127.  
  128. /* called from tk_yield if udpdata has arrived */
  129.  
  130. tftp_upcall()
  131. {
  132.     int count = 0;
  133.     OSErr errcode;
  134.     
  135.     if (tfsdata) {
  136.         /* it's on the TFTP request socket */
  137.         tfsdata = FALSE;
  138.         p_host = tfspb.csParam.receive.remoteHost;
  139.         p_port = tfspb.csParam.receive.remotePort;
  140.         mtcp_tfshnd(tfspb.csParam.receive.rcvBuff, 
  141.             tfspb.csParam.receive.rcvBuffLen,
  142.             tfspb.csParam.receive.remoteHost,
  143.             tfspb.csParam.receive.remotePort,
  144.             tfspb.csParam.receive.secondTimeStamp
  145.         );
  146.  
  147.         /* now return the buffer to UDP */
  148.         tfspb.csCode = UDPBfrReturn;
  149.         if (errcode = PBControl(&tfspb, (Boolean) FALSE))
  150.             error("no buffer return tfsread");
  151.                 
  152.         /* and do another read */
  153.         tfspb.csCode = UDPRead;
  154.         tfspb.ioCompletion = tfs_read_done;
  155.         tfspb.csParam.receive.timeOut = 0;
  156.         if (errcode = PBControl(&tfspb, (Boolean) TRUE))
  157.             error("no tfsread");
  158.         tfs_read_req++;
  159.     }
  160.     if (tftpdata) {
  161.         /* data on the TFTP transfer socket */
  162.         tftpdata = FALSE;
  163.         p_host = tftppb.csParam.receive.remoteHost;
  164.         p_port = tftppb.csParam.receive.remotePort;
  165.         mtcp_tftprcv(tftppb.csParam.receive.rcvBuff, 
  166.             tftppb.csParam.receive.rcvBuffLen,
  167.             tftppb.csParam.receive.remoteHost,
  168.             tftppb.csParam.receive.remotePort,
  169.             &tftpconn
  170.         );
  171.         if (tftpconn.tf_state != DEAD) {
  172.             /* if transfer died/finished don't do another read! */
  173.         
  174.             /* now return the buffer to UDP */
  175.             tftppb.csCode = UDPBfrReturn;
  176.             if (errcode = PBControl(&tftppb, (Boolean) FALSE))
  177.                 error("no buffer return tftpread");
  178.     
  179.             /* and do another read */
  180.             tftppb.csCode = UDPRead;
  181.             tftppb.ioCompletion = tftp_read_done;
  182.             tftppb.csParam.receive.timeOut = 0;
  183.             if (errcode = PBControl(&tftppb, (Boolean) TRUE)) {
  184.                 error("no tftpread");
  185.             }
  186.             tftp_read_req++;
  187.         }
  188.     }
  189. }
  190.  
  191. /* write a tftp packet */
  192.  
  193. mtcp_tf_write(cn, len)
  194.     register struct tfconn *cn;
  195.     unsigned len; 
  196. {
  197.     register struct tfack *packet;
  198.     unsigned res;
  199.  
  200.     packet = cn->tf_outp;
  201.     if (packet->tf_op == RRQ || packet->tf_op == WRQ) {
  202.         cn->tf_tries = REQTRIES;
  203.     }
  204.     else 
  205.         cn->tf_tries = TFTPTRIES;
  206.  
  207.     cn->tf_lastlen = len;
  208.     cn->tf_snt++;
  209.     res = (macudp_write(cn, packet, len) == 0) ? -1 : 0;
  210.  
  211.     tm_tset((int) cn->tf_rt, mtcp_tftptmo, cn, cn->tf_tm);
  212.     cn->tf_sent = cticks;
  213.     cn->tf_NR = 1;
  214. }
  215.  
  216.  
  217. /* Dump a connection block for debugging purposes. */
  218.  
  219. #ifdef TFTPDEBUG
  220.  
  221. tfcndump(cn)
  222.     register struct tfconn *cn; 
  223. {
  224.     printf("Connection addr = %04x\n", cn);
  225.     printf("lastlen = %u\texpected = %u\n",
  226.                 cn->tf_lastlen, cn->tf_expected);
  227.     printf("state = %u\tdir = %u\tmode = %u\n",
  228.                 cn->tf_state, cn->tf_dir, cn->tf_mode);
  229.     printf("sent = %u\trcvd = %u\tous = %u\tmo = %u\trsnd = %u\n\n",
  230.         cn->tf_snt, cn->tf_rcv, cn->tf_ous,cn->tf_ntmo, cn->tf_rsnd);
  231.     printf("round trip delay = %U\tK = %u\tcurnt tmo = %U\n",
  232.             cn->tf_trt, cn->tf_K, cn->tf_rt);
  233.     printf("size = %U\n", cn->tf_size);
  234. }
  235. #endif
  236.  
  237. #ifdef DOLOG
  238.  
  239. /* Log a connection block.*/
  240.  
  241. tfcnlog(cn)
  242.     register struct tfconn *cn; 
  243. {
  244.     log(tftplog, "snt=%u rcvd=%u ous=%u tmo=%u rsnd=%u trt=%U",
  245.         cn->tf_snt, cn->tf_rcv, cn->tf_ous, cn->tf_ntmo, cn->tf_rsnd, cn->tf_trt);
  246. }
  247.  
  248. #endif
  249.  
  250. /* patch the cn structure host/port to send a packet to a host w/ no connection */
  251.  
  252. mtcp_tfrpyerr(cn, code, text)
  253.     struct tfconn *cn; 
  254.     unsigned code;
  255.     char *text; 
  256. {
  257.     ip_addr savehost;
  258.     unsigned short saveport;
  259.     
  260.     savehost = cn->tf_host;
  261.     saveport = cn->tf_port;
  262.     cn->tf_host = p_host;
  263.     cn->tf_port = p_port;
  264.     
  265.     mtcp_tfudperr(cn, code, text);
  266.     
  267.     cn->tf_host = savehost;
  268.     cn->tf_port = saveport;
  269. }
  270.  
  271.  
  272. /* Send an error packet. If the code is nonzero, put it in the packet.
  273.     Otherwise, copy the text into the packet. */
  274.  
  275. char *errors[] = {
  276.     "The JNC Memorial BUGHALT",
  277.     "File not found",
  278.     "Access violation",
  279.     "Disk full",
  280.     "Illegal TFTP operation",
  281.     "Unknown transfer ID",
  282.     "File already exists",
  283.     "No such user"
  284. };
  285.  
  286.  
  287. mtcp_tfudperr(cn, code, text)
  288.     struct tfconn *cn; 
  289.     unsigned code;
  290.     char *text; 
  291. {
  292.     unsigned len;
  293.     struct tferr perr;
  294.     len = 4;
  295.  
  296.     perr.tf_op = ERROR;
  297.     perr.tf_code = code;
  298.  
  299.     if (code == ERRTXT && text != NULL) {
  300.         strncpy(&perr.tf_err[0], text, TFERRLEN);
  301.         len += strlen(text) + 1;
  302.     }
  303.     else {
  304.         strncpy(&perr.tf_err[0], errors[code], TFERRLEN);
  305.         len += strlen(errors[code]) + 1;
  306.     }
  307. #ifdef TFTPDEBUG
  308.     if (NDEBUG & APTRACE)
  309.          printf("TFTP:  Sending error packet, code %u, <%s>\n", 
  310.                 code, perr.tf_err);
  311. #endif
  312.     return(macudp_write(cn, &perr, len));
  313. }
  314.  
  315.  
  316. /* Cleanup routine called when done */
  317.  
  318. long mtcp_tfcleanup(cn)
  319. struct tfconn *cn; 
  320. {
  321.     long size;
  322.  
  323. #ifdef TFTPDEBUG
  324.     if (NDEBUG & INFOMSG)
  325.         printf("TFCLEANUP called\n");
  326. #endif
  327.     if (cn->tf_mode != TEST) 
  328.         fclose(cn->tf_fd);
  329.     macudp_close(cn);
  330.  
  331.     tm_clear(cn->tf_tm);
  332.     tm_free(cn->tf_tm);
  333.     cn->tf_tm = NULL;
  334.     
  335.     free(cn->tf_outp);
  336.     cn->tf_outp = NULL;
  337.     
  338.     cn->tf_state = DEAD;
  339. /*    tfcndump(cn);    */
  340. #ifdef DOLOG
  341.     tfcnlog(cn);
  342. #endif
  343.     size = cn->tf_size;
  344.  
  345.     return(size);
  346. }
  347.  
  348.  
  349. macudp_write(cn, packet, len)
  350. struct tfconn * cn;
  351. char * packet;
  352. int len;
  353. {
  354.     UDPiopb wpb;
  355.     OSErr errcode;
  356.     struct trash {
  357.         wdsEntry udp;
  358.         int term;
  359.     } wds;
  360.     
  361.     wds.udp.length = len;
  362.     wds.udp.ptr = packet;
  363.     wds.term = 0;
  364.     
  365.     wpb.ioCRefNum = ipp_refnum;
  366.     wpb.csCode = UDPWrite;
  367.     wpb.udpStream = cn->stream;
  368.     wpb.csParam.send.remoteHost = cn->tf_host;
  369.     wpb.csParam.send.remotePort = cn->tf_port;
  370.     wpb.csParam.send.wdsPtr = &wds;
  371.     wpb.csParam.send.checkSum = (Boolean) TRUE;
  372.     
  373.     if (errcode = PBControl(&wpb, (Boolean) FALSE)) {
  374.         error("macudp_write failed");
  375.     }
  376. }
  377.  
  378.  
  379. macudp_close(cn)
  380. struct tfconn *cn;
  381. {
  382.     UDPiopb cpb;
  383.     
  384.     cpb.ioCRefNum = ipp_refnum;
  385.     cpb.csCode = UDPRelease;
  386.     cpb.udpStream = cn->stream;
  387.     if (PBControl(&cpb, (Boolean) FALSE))
  388.         error("MacTCP UDP release failed");
  389. }
  390.  
  391.  
  392. /* Handle an incoming ack */
  393.  
  394. mtcp_tfdoack(cn, ack, len)
  395.     register struct tfconn *cn;
  396.     register struct tfack *ack;
  397.     unsigned len; 
  398. {
  399.     if (ack->tf_block == cn->tf_expected) {
  400.         tf_rtt(cn);
  401.         tm_clear(cn->tf_tm);
  402.  
  403.         cn->tf_state = RCVACK;        
  404.         tfssend(cn);
  405.     }
  406.     else {
  407.         /* We have received an ACK,
  408.             but not for the data block we sent.  It must be for
  409.             a duplicate, since we wouldn't have sent
  410.             the current data block if we hadn't gotten an ACK for
  411.             the previous one.  This duplicate ACK means either
  412.             that the network resent a packet that it wasn't sure
  413.             got through, or else the other end resent the ACK
  414.             because our current data block is lost or late.
  415.             In either case, we can safely ignore this extra ACK,
  416.             and if the ACK we want doesn't come our own timer will
  417.             get us started again.  It isn't safe
  418.             to resend the current data block now unless we are
  419.             absolutely certain that the other end won't reack
  420.             it if the earlier send was just delayed.  
  421.             */
  422.  
  423.         cn->tf_ous++;
  424. #ifdef TFTPDEBUG
  425.         if (NDEBUG & APTRACE)
  426.              printf("TFTP: ACK for block %u received again.\n",
  427.                          ack->tf_block);
  428. #endif
  429.     }
  430. }
  431.  
  432.  
  433. /* ack a certain block number */
  434.  
  435. mtcp_tfsndack(cn, number)
  436.     register struct tfconn *cn;
  437.     unsigned number; 
  438. {
  439.     register struct tfack *pack;
  440.  
  441.     pack = (struct tfack *) cn->tf_outp;
  442.     cn->tf_lastlen = sizeof(struct tfack);
  443.     pack->tf_op = ACK;
  444.     pack->tf_block = number;
  445. #ifdef TFTPDEBUG
  446.     if (NDEBUG & APTRACE) 
  447.         printf("TFTP:  ACKing block %u\n", number);
  448. #endif
  449.     return(mtcp_tf_write(cn, sizeof(struct tfack)));
  450. }
  451.  
  452. /* timeout has occured, retry or kill? */
  453.  
  454. mtcp_tftptmo(cn)
  455.     register struct tfconn *cn; 
  456. {
  457. #ifdef TFTPDEBUG
  458.     if (NDEBUG & TMO) 
  459.         printf("TFTP: Timeout.\n");
  460. #endif
  461.     cn->tf_ntmo++;
  462.     if (--cn->tf_tries) {
  463.         /* do a(nother) retry */
  464. #ifdef TFTPDEBUG
  465.         if (NDEBUG & APTRACE) 
  466.             printf("TFTP:  resending\n");
  467. #endif
  468.         cn->tf_rsnd++;
  469.         cn->tf_NR++;
  470.         macudp_write(cn, cn->tf_outp, cn->tf_lastlen);
  471.         tm_clear(cn->tf_tm);
  472.         tm_tset((int) cn->tf_rt, mtcp_tftptmo, cn, cn->tf_tm);
  473.     }
  474.     else {
  475.         cn->tf_state = TIMEOUT;
  476.         if (cn->tf_dir == PUT)
  477.             tfssend(cn);
  478.         else
  479.             tfsrcv(cn);
  480.     }
  481. }
  482.  
  483. mtcp_tfkill(cn) 
  484. register struct tfconn *cn;
  485. {
  486.     tm_clear(cn->tf_tm);
  487.     cn->tf_state = DEAD;
  488.     if (cn->tf_dir == PUT)
  489.         tfsrcv(cn);
  490.     else
  491.         tfssend(cn);
  492. }
  493.  
  494.  
  495.  
  496.  
  497. /* Process a data packet received for TFTP connection cn, according to the
  498.     type (ASCII, IMAGE, TEST) specified in the connection block. Also
  499.     handle out of secquence blocks and check on block length. If a block
  500.     is way to short (len < tftp header size) send back an error message
  501.     and abort the transfer; we have CSR disease. If the block is less
  502.     than 512 bytes long, shut down the transfer; we're done.
  503.     Otherwise, just write it to disk (if necessary).
  504. */
  505.  
  506. mtcp_tfdodata(cn, ptfdat, len)
  507.     register struct tfconn *cn;
  508.     struct tfdata *ptfdat;
  509.     unsigned len; 
  510. {
  511.     register char *data;
  512.     unsigned count;
  513.     static int crseen = FALSE;
  514.     extern char macfile[];
  515.  
  516.     if (len < 4) {
  517.         mtcp_tfudperr(cn, ERRTXT, "You have CSR disease.");
  518.             /* rpy */
  519.         mtcp_tfkill(cn);
  520.         return(0);
  521.     }
  522.  
  523.     len -= 4;                /* BAD. */
  524.  
  525.     if (ptfdat->tf_block != cn->tf_expected) {
  526.         /*    We got a retransmission of a packet we have already tried to
  527.             ACK.  If we retransmit the ACK, and the old ACK finally gets through also,
  528.             our correspondent will resend the next data block, and we will do the same
  529.             thing for it, on through to the end of the file.  So we shouldn't retransmit
  530.             the ACK until we are convinced that the first one was actually lost.  We will
  531.             become convinced if our own timeout waiting for the next data packet
  532.             expires.
  533.                 Here is what you shouldn't do. . .
  534.                     if (ptfdat->tf_block == cn->tf_expected-1)
  535.                         mtcp_tfsndack(cn, ptfdat->tf_block);
  536.                 And now we return to correct procedures. . .  
  537.         */
  538. #ifdef TFTPDEBUG
  539.         if (NDEBUG & (INFOMSG|PROTERR|APTRACE))
  540.             printf("TFTP:     Got block %u, expecting %u.\n",
  541.                     ptfdat->tf_block, cn->tf_expected);
  542. #endif
  543.         cn->tf_ous++;    
  544.         return(0);
  545.     }
  546.  
  547.     if (cn->tf_state != DATAWAIT) {
  548. #ifdef TFTPDEBUG
  549.         printf("TFTP:  Received unexpected data block tf_state is %d.\n",cn->tf_state);
  550. #endif
  551.         mtcp_tfudperr(cn, ERRTXT, "Rcvd unexpected data block");
  552.             /* mtcp_tfrpyerr */
  553.         mtcp_tfkill(cn);
  554.         return(0);
  555.     }
  556.  
  557.     tm_clear(cn->tf_tm);
  558.     tf_rtt(cn);
  559.  
  560.     cn->tf_size += len;
  561.     data = ptfdat->tf_data;
  562.  
  563.     if (cn->tf_mode == IMAGE || cn->tf_mode == TEST || cn->tf_mode == OCTET) {
  564.         if (cn->tf_mode != TEST && fwrite(data, 1, len, cn->tf_fd) != len) 
  565.         {
  566.             mtcp_tfudperr(cn, DISKFULL, &macfile[0]);
  567.             /* printf("TFTP: disk is full!\n"); */
  568.             mtcp_tfkill(cn);    
  569.             return(0);
  570.         }
  571.     }
  572.     else if (cn->tf_mode == ASCII) {
  573.         register char thechar;
  574.  
  575.         for (count = len + 1; --count; ) {
  576.             if ( (thechar = *data++) ) {
  577.                 if (thechar == LF) {
  578.                     if (crseen) {
  579.                         crseen = FALSE;
  580.                         continue;
  581.                     }
  582.                     else
  583.                         thechar = CR;
  584.                 }
  585.                 else if (thechar == CR) {
  586.                     crseen = TRUE;
  587.                 }
  588.                 if (putc(thechar, cn->tf_fd) == EOF) {
  589.                     mtcp_tfudperr(cn, DISKFULL, &macfile[0]);
  590.                     /* printf("TFTP: disk is full!\n"); */
  591.                     mtcp_tfkill(cn);
  592.                     return(0);
  593.                 }
  594.             }
  595.         }
  596.     }
  597.     else {
  598.         mtcp_tfudperr(cn, ERRTXT, "Internal error");
  599.         mtcp_tfkill(cn);
  600.         return(0);
  601.     }
  602.  
  603.     if (len == NORMLEN)
  604.         cn->tf_state = RCVDATA;
  605.     else 
  606.         cn->tf_state = RCVLASTDATA;
  607.  
  608.     /* Send the ack AFTER writing the data */
  609.     mtcp_tfsndack(cn, ptfdat->tf_block);
  610.  
  611.     cn->tf_expected++;
  612.  
  613.     tfsrcv(cn);
  614. }
  615.  
  616. /* recalculate round trip time and set vars */
  617.  
  618. tf_rtt(cn)
  619.     register struct tfconn *cn; 
  620. {
  621.     long trtM;
  622.  
  623.     trtM = cticks - cn->tf_sent;  /*  Measured round trip time  */
  624.     if (cn->tf_NR_last == 1)
  625.         cn->tf_K = Kinit;
  626.  
  627.     if (cn->tf_NR == 1)
  628.         cn->tf_trt = (trtM + cn->tf_trt) / 2;
  629.     else {
  630.         if ((cn->tf_NR_last > 1) && (cn->tf_K > 1) )
  631.             cn->tf_K -= Kinc;
  632.         cn->tf_trt += cn->tf_trt / cn->tf_K;
  633.     }
  634.     cn->tf_rt = max(min(cn->tf_trt * TMMULT, MAXTMO), MINTICKS);
  635.     cn->tf_NR_last = cn->tf_NR;
  636. }
  637.  
  638.  
  639.  
  640. /* Handle an incoming packet after a connection has been opened */
  641.  
  642. mtcp_tftprcv(pdata, len, fhost, port, cn)
  643.     struct tfdata *pdata;
  644.     unsigned len;
  645.     ip_addr fhost;
  646.     unsigned short port;
  647.     struct tfconn *cn; 
  648. {
  649.     unsigned op;
  650.  
  651.     cn->tf_rcv++;
  652.  
  653.     op = pdata->tf_op;
  654.     pdata->tf_op = op;
  655.  
  656.     switch (op) {
  657.         case DATA: {
  658.             if (mtcp_tfckport(cn, pdata, port))
  659.                 mtcp_tfdodata(cn, pdata, len);
  660.             break;
  661.         }
  662.         case ACK: {
  663.             if (mtcp_tfckport(cn, pdata, port))
  664.                 mtcp_tfdoack(cn, pdata, len);
  665.             break;
  666.         }
  667.         case ERROR: {
  668.             if ((cn->tf_haveport == 0) ||
  669.                     (cn->tf_port == port)) {
  670.                 mtcp_tfdoerr(cn, pdata, len);
  671.                 mtcp_tfkill(cn);
  672.             }
  673. #ifdef TFTPDEBUG
  674.             else if (NDEBUG & ROUTE) {
  675.                 printf("TFTP:  ignoring error packet.\n");
  676.                 mtcp_tfdoerr(cn, pdata, len);
  677.             }
  678. #endif
  679.             break;
  680.         }
  681.         default: {
  682.             error("mtcp_tftprcv: Got bad opcode %u", op);
  683.             mtcp_tfudperr(cn, ILLTFTP, " ");
  684.             mtcp_tfkill(cn);
  685.             break;
  686.         }
  687.     }
  688.     return(0);
  689. }
  690.  
  691.  
  692. mtcp_tfsndata(cn, len)
  693.     register struct tfconn *cn;
  694.     unsigned len; 
  695. {
  696.     register struct tfdata *tfdata;
  697.  
  698.     tfdata = cn->tf_outp;
  699.     tfdata->tf_op = DATA;
  700.     tfdata->tf_block = cn->tf_expected;
  701.  
  702. #ifdef DEBUG
  703.     if (NDEBUG & APTRACE) 
  704.         printf("TFTP:  sending block %u\n", tfdata->tf_block);
  705. #endif
  706.     return(mtcp_tf_write(cn, sizeof(struct tfdata) - 512 + len));
  707. }
  708.  
  709. /* Setup a TFTP connection block. */
  710.  
  711. mttfmkcn(cn, dir, mode)
  712.     register struct tfconn * cn;
  713.     unsigned dir;
  714.     unsigned mode; 
  715. {
  716.     cn->tf_fd = NULL;
  717.     cn->tf_udp = NULL;
  718.     cn->tf_rcv = NULL;
  719.     cn->tf_snt = 0;
  720.     cn->tf_ous = 0;
  721.     cn->tf_ntmo = 0;
  722.     cn->tf_rsnd = 0;
  723.     cn->tf_dir = dir;
  724.     cn->tf_mode = mode;
  725.     cn->tf_size = 0L;
  726.     cn->tf_K = Kinit;
  727.     cn->tf_trt = T0;
  728.     cn->tf_rt = (long) min(cn->tf_trt * TMMULT, MAXTMO);
  729.     cn->tf_NR = 0;
  730.     cn->tf_NR_last = 1;
  731.  
  732.     
  733.     if (cn->tf_tm == NULL) {
  734.         cn->tf_tm = tm_alloc();
  735.         if (cn->tf_tm == NULL) {
  736.             error("TFTP: Couldn't allocate timer");
  737.             return(-1);
  738.         }
  739.     }
  740.     if (cn->tf_outp == NULL) {
  741.         cn->tf_outp = malloc(NORMLEN);
  742.         if (cn->tf_outp == NULL) {
  743.             error("TFTP: Couldn't allocate output packet");
  744.             tm_free(cn->tf_tm);
  745.             cn->tf_tm = NULL;
  746.             return(-2);
  747.         }
  748.     }
  749.     return(0);
  750. }
  751.  
  752.  
  753. /*  Check over the port in the incoming packet  */
  754.  
  755. mtcp_tfckport(cn, pdata, pfport)
  756.     register struct tfconn *cn;
  757.     register struct tfdata *pdata;
  758.     unsigned short pfport;
  759. {
  760.     if (cn->tf_haveport == 0) {
  761.         /*  Foreign port not yet identified, save it. */
  762.         if (cn->tf_expected == pdata->tf_block) {
  763.             /* but only if this is a response to our request.  */
  764.             cn->tf_haveport = TRUE;
  765.             cn->tf_port = pfport;
  766.         }
  767.         else  {
  768. #ifdef TFTPDEBUG
  769.             if (NDEBUG & (PROTERR|NETERR))
  770.                 printf("TFTP:  Received packet from old connection.\n");
  771.                 printf("       Expected block %u, got block %u\n",
  772.                     cn->tf_expected, pdata->tf_block);
  773. #endif
  774.             mtcp_tfrpyerr(cn, ERRTXT, "Rcvd data on old connection");
  775.                 /* rpy */
  776.             return(FALSE);
  777.         }
  778.     }
  779.     else if (cn->tf_port != pfport) {
  780. #ifdef TFTPDEBUG
  781.         if (NDEBUG & (PROTERR|NETERR)) {
  782.             printf("TFTP: Rcvd pkt from port %04x, expect port %04x,\n",
  783.                 pfport, cn->tf_port);
  784.         }
  785. #endif
  786.         mtcp_tfrpyerr(cn, BADTID, " ");
  787.             /* rpy */
  788.         return(FALSE);
  789.     }
  790.     return(TRUE);
  791. }
  792.  
  793.  
  794. /* Process an incoming error packet */
  795.  
  796. mtcp_tfdoerr(cn, perr, len)
  797.     register struct tfconn *cn;
  798.     struct tferr * perr;
  799.     unsigned len; 
  800. {
  801.     char terror[100];
  802.  
  803.     sprintf(terror, "TFTP: Error from host: \"%s\"", &perr->tf_err[0]);
  804.     error(terror);
  805. }
  806.  
  807.